<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>五子棋</title>
</head>
<style>
    canvas {
        display: flex;
        margin: 0 auto;
        background-color: #0a0;
    }

    #tips {
        font-size: 16px;
        text-align: center;
    }
</style>

<body>
    <div id="tips">请黑子落子</div>
    <canvas width="800" height="800" id="canvas"></canvas>
</body>
<script>
    let tips = document.getElementById('tips')
    let canvas = document.getElementById('canvas')
    let context = canvas.getContext('2d')

    //画棋盘格
    for (let i = 1; i <= 15; i++) {
        //横线
        context.beginPath()
        context.moveTo(50, 50 * i)
        context.lineTo(750, 50 * i)
        context.stroke()
        context.closePath()

        //竖线
        context.beginPath()
        context.moveTo(50 * i, 50)
        context.lineTo(50 * i, 750)
        context.stroke()
        context.closePath()
    }

    let win = false;

    //棋盘棋子二维数组
    let pointsArr = []
    for (let i = 1; i <= 15; i++) {
        pointsArr[i] = []
    }

    let isBlack = true

    //点击落子
    canvas.addEventListener('click', function (e) {
        if (win) {
            return
        }

        let { offsetX, offsetY } = e
        //棋盘边缘位置不要落子
        if (offsetX < 25 || offsetX > 775 || offsetY < 25 || offsetY > 775) {
            return
        }
        //四舍五入 让棋子在交叉点中心位置
        let i = Math.round(offsetX / 50)
        let j = Math.round(offsetY / 50)

        //判断这个位置有没有棋子
        if (pointsArr[i][j]) {
            return
        }
        pointsArr[i][j] = isBlack ? 'black' : 'white' //存储棋子
        let x = i * 50
        let y = j * 50

        context.beginPath()
        context.arc(x, y, 25, 0, 2 * Math.PI)
        //给棋子加样式
        let g = null
        if (isBlack) {
            g = context.createRadialGradient(x - 10, y - 10, 0, x - 10, y - 10, 30)
            g.addColorStop(0, '#ccc')
            g.addColorStop(1, '#000')
        } else {
            g = context.createRadialGradient(x + 10, y + 10, 0, x + 10, y + 10, 30)
            g.addColorStop(0, '#666')
            g.addColorStop(1, '#fff')
        }
        context.fillStyle = g
        context.fill()
        context.closePath()

        win = checkWin(i, j)
        if (win) {
            tips.innerText = (isBlack ? '黑子' : '白子') + '赢啦'
            return
        }

        isBlack = !isBlack
        tips.innerText = '请' + (isBlack ? '黑子' : '白子') + '落子'
    })

    let next = 0
    let prev = 0
    function checkWin(row, col) {
        let target = pointsArr[row][col]

        //横向判断
        for (let i = 1; i < 5; i++) {
            if (pointsArr[row + i][col] && pointsArr[row + i][col] == target) {
                next++
            } else {
                break
            }
        }
        for (let i = 1; i < 5; i++) {
            if (pointsArr[row - i][col] && pointsArr[row - i][col] == target) {
                prev++
            } else {
                break
            }
        }
        //为什么是4 因为落子本身也是一个 还需要4个就可以五子成功
        if (next + prev >= 4) {
            return true
        }

        next = 0
        prev = 0
        //纵向判断
        for (let i = 1; i < 5; i++) {
            if (pointsArr[row][col + i] && pointsArr[row][col + i] == target) {
                next++
            } else {
                break
            }
        }
        for (let i = 1; i < 5; i++) {
            if (pointsArr[row][col - i] && pointsArr[row][col - i] == target) {
                prev++
            } else {
                break
            }
        }
        if (next + prev >= 4) {
            return true
        }

        next = 0
        prev = 0
        //斜向判断
        for (let i = 1; i < 5; i++) {
            if (pointsArr[row + i][col + i] && pointsArr[row + i][col + i] == target) {
                next++
            } else {
                break
            }
        }
        for (let i = 1; i < 5; i++) {
            if (pointsArr[row - i][col - i] && pointsArr[row - i][col - i] == target) {
                prev++
            } else {
                break
            }
        }
        if (next + prev >= 4) {
            return true
        }
    }

</script>

</html>